﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using LockCrypt.Core;

namespace LockCrypt {
    /// <summary>
    /// Displays estimated entropy of a password.
    /// </summary>
    public partial class PasswordAnalyser : UserControl {
        public static readonly DependencyProperty BitStrengthProperty = DependencyProperty.Register("BitStrength", typeof(int), typeof(PasswordAnalyser), new PropertyMetadata(0, new PropertyChangedCallback(BitStrength_Changed)));
        /// <summary>
        /// Gets or sets the bit strength displayed.
        /// </summary>
        /// <value>The currently bit strength displayed.</value>
        public int BitStrength {
            get { return Convert.ToInt32(base.GetValue(BitStrengthProperty)); }
            set { base.SetValue(BitStrengthProperty, value); }
        }

        /// <summary>
        /// Sets the descriptive text when the bit strength changes.
        /// </summary>
        public static void BitStrength_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e) {
            PasswordAnalyser ctl = d as PasswordAnalyser;
            ctl.txtBitStrength.Text = string.Format("{0} bits", ctl.BitStrength);
            double bitStrengthRating = (ctl.BitStrength / 80.0) * 100; // 80 as an arbitrary perfect bit strength
            ctl.SetRating(bitStrengthRating > 100 ? 100 : bitStrengthRating < 0 ? 0 : Convert.ToInt32(bitStrengthRating));
        }

        public static readonly DependencyProperty PasswordProperty = DependencyProperty.Register("Password", typeof(string), typeof(PasswordAnalyser), new PropertyMetadata(new PropertyChangedCallback(Password_Changed)));
        /// <summary>
        /// Gets or sets the currently displayed password.
        /// </summary>
        /// <value>The currently displayed password.</value>
        public string Password {
            get { return Convert.ToString(base.GetValue(PasswordProperty)); }
            set { base.SetValue(PasswordProperty, value); }
        }

        /// <summary>
        /// Re-analyzes the password when it changes.
        /// </summary>
        public static void Password_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e) {
            PasswordAnalyser ctl = d as PasswordAnalyser;
            if(ctl.Password == null) {
                ctl.Analysis = null;
                ctl.txtRating.Text = I18nUtils.GetString("Strings", "NoneSelected");
            } else {
                ctl.Analysis = PasswordAnalyzer.CheckStrength(ctl.Password);
            }
        }

        public static readonly DependencyProperty AnalysisProperty = DependencyProperty.Register("Analysis", typeof(PasswordAnalyzer.PasswordAnalysis), typeof(PasswordAnalyser), new PropertyMetadata(new PropertyChangedCallback(Analysis_Changed)));
        /// <summary>
        /// Gets or sets an analysis of the current password.
        /// </summary>
        /// <value>An analysis of the current password.</value>
        public PasswordAnalyzer.PasswordAnalysis Analysis {
            get { return base.GetValue(AnalysisProperty) as PasswordAnalyzer.PasswordAnalysis; }
            private set { base.SetValue(AnalysisProperty, value); }
        }

        /// <summary>
        /// Updates the background color when the password analysis changes.
        /// </summary>
        private static void Analysis_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e) {
            PasswordAnalyser ctl = d as PasswordAnalyser;
            if(ctl.Analysis == null) {
                ctl.backgroundLeft.Color = Colors.White;
                ctl.backgroundRight.Color = Colors.White;
                ctl.BitStrength = 0;
            } else {
                ctl.BitStrength = ctl.Analysis.BitStrength;
                ctl.SetRating(ctl.Analysis.PercentageScore);
            }
        }

        private void SetRating(decimal percentage) {
            backgroundLeft.Color = CalculateRatingColor(percentage);
            backgroundRight.Color = CalculateRatingColor(percentage + 20);
            if(percentage > 100) { percentage = 100; } else if(percentage < 0) { percentage = 0; }
            string strength = string.Empty;
            if(percentage < 20) {
                strength = I18nUtils.GetString("Strings", "VeryWeak");
            } else if(percentage < 40) {
                strength = I18nUtils.GetString("Strings", "Weak");
            } else if(percentage < 60) {
                strength = I18nUtils.GetString("Strings", "Good");
            } else if(percentage < 80) {
                strength = I18nUtils.GetString("Strings", "Strong");
            } else if(percentage <= 100) {
                strength = I18nUtils.GetString("Strings", "VeryStrong");
            }
            decimal roundedPercentage = Math.Round(percentage, 0)/100;
            txtRating.Text = string.Format("{0:0%} - {1}", roundedPercentage, strength);
        }

        public PasswordAnalyser() {
            InitializeComponent();
        }

        /// <summary>
        /// Calculates the color for a rating percentage.
        /// </summary>
        /// <param name="percentage">The percentage.</param>
        /// <returns>A color indicating the strength for the percentage.</returns>
        private static Color CalculateRatingColor(decimal percentage) {
            if(percentage <= 0) {
                percentage = 0;
            } else if(percentage >= 100) {
                percentage = 100;
            }
            float percentageF = Convert.ToSingle(percentage);
            //float res = 5F * (percentageF / 100F);
            float res = (percentageF / 120F)*100F;
            var hsbColor = new HLSRGB(res, 0.8F, 1F);
            return hsbColor.Color;
        }
    }
}
